﻿using System.IO;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.InteropServices.ComTypes;
using BaseData.Exts;
using BaseData.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web.UI.WebControls;

namespace WebUI
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            var list = new List<DataTableClass.Convert>
            {
                new DataTableClass.Convert() { Assembly = new Web_Base_News_Node().TToAssembly(), fix = "Node", take = new string[] { "PkId", } },
                //new CAncp() { table = new Web_Base_News_Node_Ext().TToANCP(), fix = "Node", take = new string[] { "PkId", }, skip = new string[] {"PkId"}, },
                new DataTableClass.Convert() { Assembly = new Web_Base_News_Node().TToAssembly(), fix = "ParentNode", take = new string[] { "PkId", }, },
                //new CAncp() { table = new Web_Base_News_Node_Ext().TToANCP(), fix = "ParentNode", take = new string[] { "PkId", }, skip = new string[] {"PkId"}, },
                new DataTableClass.Convert() { Assembly = new Web_Base_News_Info().TToAssembly(), take = new string[] { "PkId", }, fix = "Info", },
                //new CAncp() { table = new Web_Base_News_Info_Ext().TToANCP(), fix = "Info", take = new string[] { "PkId", }, skip = new string[] {"PkId"}, },
            };
            var dtNew = list.IListConvertToDataTable();
            // foreach (DataColumn dc in dtNew.Columns) Response.Write(dc.ColumnName + " - ");
            // Response.Write("<br />\r\n");

            using (var ctx = new ContextExt())
            {
                // var itemsRfk = from q in this.RepeaterExt2.FieldKeys select q;
                // foreach (var fieldItems in itemsRfk)
                // {
                //     if (fieldItems.Key == EnumsCMS.FieldName.NodeId)
                //     {
                //         var items = fieldItems;
                //         //if (fieldItems.FieldThan == EnumsFieldThan.Great) sql = sql.Where(w => w.PkId > (int)items.SortAction);
                //         //if (fieldItems.FieldThan == EnumsFieldThan.Equal) sql = sql.Where(w => w.PkId == (int)items.SortAction);
                //         //if (fieldItems.FieldThan == EnumsFieldThan.Less) sql = sql.Where(w => w.PkId < (int)items.SortAction);
                //     }
                //     else if (fieldItems.Key == EnumsCMS.FieldName.ParentId)
                //     {
                //         var items = fieldItems;
                //         //sql = sql.Where(w => w.PkId == (int)items.SortAction);
                //     }
                //     else
                //     {
                //         sql = sql.Where(w => w.Click > 1000);
                //     }
                // }
                // 1.分别取得节点、内容表结构，转为相应的DataTable结构。
                // var dtInfos = new Web_Base_News_Info().TToDataTable();
                // var dtNodes = new Web_Base_News_Node().TToDataTable("Node");
                // var dtParent = new Web_Base_News_Node().TToDataTable("ParentNode");
                // // 2.根据相应的DataTable结构，组合为一个包含三表结构的新表。
                // for (var i = 0; i < dtInfos.Columns.Count; i++) dtNew.Columns.Add(dtInfos.Columns[i].ColumnName);
                // for (var i = 0; i < dtNodes.Columns.Count; i++) dtNew.Columns.Add(dtNodes.Columns[i].ColumnName);
                // for (var i = 0; i < dtParent.Columns.Count; i++) dtNew.Columns.Add(dtParent.Columns[i].ColumnName);

                // this.GetRows(ctx, dtNew, this.Repeater1, new List<int>() { 8 }, 0, 5);
                // this.GetRows(ctx, dtNew, this.RepeaterExt1, new List<int>() { 8 }, 0, 5);
            }
        }
        public void GetRows(ContextExt ctx, DataTable dtNew, Repeater repeater, List<int> list, int skip, int take)
        {
            dtNew.Clear();
            // 3.根据查询条件，分别查询得到Info、Node和Parent表的内容。
            var infox = (from q in ctx.Web_Base_News_Info where list.Contains(q.NodeId ?? 0) select q);
            var nodes = (from q in ctx.Web_Base_News_Node where infox.Select(s => s.NodeId).Contains(q.PkId) select q);
            var parent = (from q in ctx.Web_Base_News_Node where nodes.Select(s => s.ParentId).Contains(q.PkId) select q);
            // 4.1.以Info为导航对DataTable进行赋值
            var dict = new Dictionary<string, DataRow>();
            var infos = infox.OrderBy(o => o.NodeId).ThenByDescending(o => o.SortId).Skip(skip).Take(take).ToList();
            foreach (var info in infos)
            {
                var dataRow = dtNew.NewRow();
                foreach (var propertyInfo in typeof(Web_Base_News_Info).GetProperties()) dataRow["Info" + propertyInfo.Name] = propertyInfo.GetValue(info, null);
                dtNew.Rows.Add(dataRow);
                /* 方案二：主表加入字典 */
                ///var pNode = (from q in nodes where q.PkId == info.NodeId select q).FirstOrDefault();
                ///dict.Add(pNode.ParentId + "-" + info.NodeId + "-" + info.PkId, dataRow);
            }
            // foreach (DataRow dr in dtNew.Rows) dict.Add(dr["PkId"], dr);
            // 4.2.用nodes填充DataTable的Node部分
            foreach (var node in nodes.ToList())
            {
                /// var drx = from q in dict where q.Key.StartsWith(node.ParentId + "-" + node.PkId + "-") select q;
                /* 方案二：子表加入字典 */
                /// foreach (var dx in drx)
                /// {
                ///     var fields = node.GetType().GetProperties();
                ///     foreach (var field in fields)
                ///     {
                ///         dx.Value["Node" + field.Name] = field.GetValue(node, null) ?? DBNull.Value;
                ///     }
                /// }
                var drs = dtNew.Select("InfoNodeId='" + node.PkId + "'");
                foreach (var dr in drs)
                {
                    var fields = node.GetType().GetProperties();
                    foreach (var field in fields) dr["Node" + field.Name] = field.GetValue(node, null) ?? DBNull.Value;
                }
            }
            /// // 4.3.用parent填充DataTable的ParentNode部分
            foreach (var node in parent.ToList())
            {
                /* 方案二：附表加入字典 */
                /// var drx = from q in dict where q.Key.StartsWith(node.PkId + "-") select q;
                /// foreach (var dx in drx)
                /// {
                ///     var fields = node.GetType().GetProperties();
                ///     foreach (var field in fields)
                ///     {
                ///         dx.Value["ParentNode" + field.Name] = field.GetValue(node, null) ?? DBNull.Value;
                ///     }
                /// }
                var drs = dtNew.Select("NodeParentId='" + node.PkId + "'");
                foreach (var dr in drs)
                {
                    var fields = node.GetType().GetProperties();
                    foreach (var field in fields) dr["ParentNode" + field.Name] = field.GetValue(node, null) ?? DBNull.Value;
                }
            }
            /* 方案二：字典加入DataTable */
            /// /// var resx = (from q in dict select q.Value);
            /// /// foreach (DataRow res in resx)
            /// /// {
            /// ///     dtNew.Rows.Add(res);
            /// /// }
            //repeater.DataSource = dtNew;
            //repeater.DataBind();
        }
    }
    /// <summary>
    /// Summary description for LinqToDataTable
    /// </summary>
    public static class LinqToDataTable
    {
    }
    /// <summary>
    /// 类属性/字段的值复制工具
    /// </summary>
    public class ClassValueCopier
    {
        /// <summary>
        /// 复制
        /// </summary>
        /// <param name="destination">目标</param>
        /// <param name="source">来源</param>
        /// <returns>成功复制的值个数</returns>
        public static int Copy(object destination, object source)
        {
            if (destination == null || source == null) return 0;
            return Copy(destination, source, source.GetType());
        }
        /// <summary>
        /// 复制
        /// </summary>
        /// <param name="destination">目标</param>
        /// <param name="source">来源</param>
        /// <param name="type">复制的属性字段模板</param>
        /// <returns>成功复制的值个数</returns>
        public static int Copy(object destination, object source, Type type)
        {
            return Copy(destination, source, type, null);
        }
        /// <summary>
        /// 复制
        /// </summary>
        /// <param name="destination">目标</param>
        /// <param name="source">来源</param>
        /// <param name="type">复制的属性字段模板</param>
        /// <param name="excludeName">排除下列名称的属性不要复制</param>
        /// <returns>成功复制的值个数</returns>
        public static int Copy(object destination, object source, Type type, IEnumerable<string> excludeName)
        {
            if (destination == null || source == null)
            {
                return 0;
            }
            if (excludeName == null)
            {
                excludeName = new List<string>();
            }
            var i = 0;
            var desType = destination.GetType();
            var enumerable = excludeName as string[] ?? excludeName.ToArray();
            foreach (var fieldInfo in type.GetFields())
            {
                if (enumerable.Contains(fieldInfo.Name))
                {
                    continue;
                }
                //try
                {
                    var des = desType.GetField(fieldInfo.Name);
                    if (des != null && des.FieldType == fieldInfo.FieldType)
                    {
                        des.SetValue(destination, fieldInfo.GetValue(source));
                        i++;
                    }
                }
                //catch
                {
                }
            }
            foreach (var pi in type.GetProperties())
            {
                if (enumerable.Contains(pi.Name)) continue;
                //try
                {
                    var des = desType.GetProperty(pi.Name);
                    if (des != null && des.PropertyType == pi.PropertyType && des.CanWrite && pi.CanRead)
                    {
                        des.SetValue(destination, pi.GetValue(source, null), null);
                        i++;
                    }
                }
                //catch
                {
                    //throw ex;
                }
            }
            return i;
        }
    }
    #region 扩展方法 For .NET 3.0+
    /// <summary>
    /// 类属性/字段的值复制工具 扩展方法
    /// </summary>
    public static class ClassValueCopier2
    {
        /// <summary>
        /// 获取实体类的属性名称
        /// </summary>
        /// <param name="source">实体类</param>
        /// <returns>属性名称列表</returns>
        public static List<string> GetPropertyNames(this object source)
        {
            return source == null ? new List<string>() : GetPropertyNames(source.GetType());
        }

        /// <summary>
        /// 获取类类型的属性名称
        /// </summary>
        /// <param name="source">类类型</param>
        /// <param name="declarationOrder">是否按声明顺序排序</param>
        /// <returns>属性名称列表</returns>
        public static List<string> GetPropertyNames(this Type source, bool declarationOrder = true)
        {
            if (source == null)
            {
                return new List<string>();
            }
            var list = source.GetProperties().AsQueryable();
            if (declarationOrder)
            {
                list = list.OrderBy(p => p.MetadataToken);
            }
            return list.Select(o => o.Name).ToList(); ;
        }

        /// <summary>
        /// 从源对象赋值到当前对象
        /// </summary>
        /// <param name="destination">当前对象</param>
        /// <param name="source">源对象</param>
        /// <param name="excludeName">排除下列名称的属性不要复制</param>
        /// <returns>成功复制的值个数</returns>
        public static int CopyValueFrom(this object destination, object source, IEnumerable<string> excludeName = null)
        {
            if (destination == null || source == null)
            {
                return 0;
            }
            return ClassValueCopier.Copy(destination, source, source.GetType(), excludeName);
        }
        /// <summary>
        /// 从当前对象赋值到目标对象
        /// </summary>
        /// <param name="source">当前对象</param>
        /// <param name="destination">目标对象</param>  
        /// <returns>成功复制的值个数</returns>
        public static int CopyValueTo(this object source, object destination)
        {
            return CopyValueTo(destination, source, null);
        }
        /// <summary>
        /// 从当前对象赋值到目标对象
        /// </summary>
        /// <param name="source">当前对象</param>
        /// <param name="destination">目标对象</param>  
        /// <param name="excludeName">排除下列名称的属性不要复制</param>
        /// <returns>成功复制的值个数</returns>
        public static int CopyValueTo(this object source, object destination, IEnumerable<string> excludeName)
        {
            return destination == null || source == null
                ? 0
                : ClassValueCopier.Copy(destination, source, source.GetType(), excludeName);
        }
    }
    #endregion
    public abstract class EntityFactory
    {
        public static T CreateEntity<T>()
        {
            var t = Activator.CreateInstance<T>();
            var properties = typeof(T).GetProperties();
            foreach (var pi in properties)
            {
                var type = pi.PropertyType;
                pi.SetValue(t, type.IsArray ? Activator.CreateInstance(type, 10) : Activator.CreateInstance(type), null);
            }
            return t;
        }
    }
    public class Entity<T>
    {
        // var sql = from q in ctx.Web_Base_News_Node select q;
        // var cus = Entity<Web_Base_News_Node>.Selects(s => new { MyName = s.FlagPass, YourName = s.Key, });
        public static TResult Selects<TResult>(Expression<Func<T, TResult>> func)
        {
            var type = typeof(TResult);
            // var t = (TResult)Activator.CreateInstance(type, new object[type.GetProperties().Length]);
            // object someValue = "";// 具体值不写了，只是做个样子
            // foreach (PropertyInfo pi in type.GetProperties())
            // {
            //     pi.SetValue(t, someValue, null); // 问题就出在这里了，如果是匿名类的话，没有Set方法。
            // }
            // return t;
            var objArr = new object[type.GetProperties().Length];
            for (var i = 0; i < type.GetProperties().Length; i++)
            {
                objArr[i] = "";// someValue.....
            }
            return (TResult)Activator.CreateInstance(type, objArr);
        }
    }
}